package org.red5.codecs.g729;

//package org.mobicents.media.server.impl.dsp.audio.g729;

public class CelpCo {

	int ACELP_codebook( /* (o) :index of pulses positions */
	float x[], /* (i) :Target vector */
			float h[], /* (i) :Impulse response of filters */
			int t0, /* (i) :Pitch lag */
			float pitch_sharp, /* (i) :Last quantized pitch gain */
			int i_subfr, /* (i) :Indicator of 1st subframe, */
			float code[], /* (o) :Innovative codebook */
			float y[], /* (o) :Filtered innovative codebook */
			IntegerPointer sign /* (o) :Signs of 4 pulses */
	) {
		int i, index;
		float dn[] = new float[LD8KConstants.L_SUBFR];
		float rr[] = new float[LD8KConstants.DIM_RR];

		/*----------------------------------------------------------------*
		 * Include fixed-gain pitch contribution into impulse resp. h[]    *
		 * Find correlations of h[] needed for the codebook search.        *
		 *-----------------------------------------------------------------*/

		if (t0 < LD8KConstants.L_SUBFR)
			for (i = t0; i < LD8KConstants.L_SUBFR; i++)
				h[i] += pitch_sharp * h[i - t0];

		cor_h(h, rr);

		/*----------------------------------------------------------------*
		 * Compute correlation of target vector with impulse response.     *
		 *-----------------------------------------------------------------*/

		CorFunc.cor_h_x(h, x, dn); /* backward filtered target vector dn */

		/*----------------------------------------------------------------*
		 * Find innovative codebook.                                       *
		 *-----------------------------------------------------------------*/

		index = d4i40_17(dn, rr, h, code, y, sign, i_subfr);

		/*------------------------------------------------------*
		 * - Add the fixed-gain pitch contribution to code[].    *
		 *-------------------------------------------------------*/

		if (t0 < LD8KConstants.L_SUBFR)
			for (i = t0; i < LD8KConstants.L_SUBFR; i++)
				code[i] += pitch_sharp * code[i - t0];

		return index;
	}

	/*--------------------------------------------------------------------------*
	 *  Function  cor_h()                                                       *
	 *  ~~~~~~~~~~~~~~~~~                                                       *
	 * Compute  correlations of h[]  needed for the codebook search.            *
	 *--------------------------------------------------------------------------*/

	static void cor_h(float[] h, /* (i) :Impulse response of filters */
			float[] rr /* (o) :Correlations of H[] */
	) {
		int rri0i0, rri1i1, rri2i2, rri3i3, rri4i4;
		int rri0i1, rri0i2, rri0i3, rri0i4;
		int rri1i2, rri1i3, rri1i4;
		int rri2i3, rri2i4;

		int p0, p1, p2, p3, p4;

		int ptr_hd, ptr_hf, ptr_h1, ptr_h2;
		float cor;
		int i, k, ldec, l_fin_sup, l_fin_inf;

		/* Init pointers */
		rri0i0 = 0;// rr;
		rri1i1 = rri0i0 + LD8KConstants.NB_POS;
		rri2i2 = rri1i1 + LD8KConstants.NB_POS;
		rri3i3 = rri2i2 + LD8KConstants.NB_POS;
		rri4i4 = rri3i3 + LD8KConstants.NB_POS;
		rri0i1 = rri4i4 + LD8KConstants.NB_POS;
		rri0i2 = rri0i1 + LD8KConstants.MSIZE;
		rri0i3 = rri0i2 + LD8KConstants.MSIZE;
		rri0i4 = rri0i3 + LD8KConstants.MSIZE;
		rri1i2 = rri0i4 + LD8KConstants.MSIZE;
		rri1i3 = rri1i2 + LD8KConstants.MSIZE;
		rri1i4 = rri1i3 + LD8KConstants.MSIZE;
		rri2i3 = rri1i4 + LD8KConstants.MSIZE;
		rri2i4 = rri2i3 + LD8KConstants.MSIZE;

		/*------------------------------------------------------------*
		 * Compute rri0i0[], rri1i1[], rri2i2[], rri3i3 and rri4i4[]  *
		 *------------------------------------------------------------*/

		p0 = rri0i0 + LD8KConstants.NB_POS - 1; /*
												 * Init pointers to last position of rrixix[]
												 */
		p1 = rri1i1 + LD8KConstants.NB_POS - 1;
		p2 = rri2i2 + LD8KConstants.NB_POS - 1;
		p3 = rri3i3 + LD8KConstants.NB_POS - 1;
		p4 = rri4i4 + LD8KConstants.NB_POS - 1;

		ptr_h1 = 0;// h;
		cor = (float) 0.0;
		for (i = 0; i < LD8KConstants.NB_POS; i++) {
			cor += h[ptr_h1] * h[ptr_h1];
			ptr_h1++;
			rr[p4--] = cor;

			cor += h[ptr_h1] * h[ptr_h1];
			ptr_h1++;
			rr[p3--] = cor;

			cor += h[ptr_h1] * h[ptr_h1];
			ptr_h1++;
			rr[p2--] = cor;

			cor += h[ptr_h1] * h[ptr_h1];
			ptr_h1++;
			rr[p1--] = cor;

			cor += h[ptr_h1] * h[ptr_h1];
			ptr_h1++;
			rr[p0--] = cor;
		}

		/*-----------------------------------------------------------------*
		 * Compute elements of: rri2i3[], rri1i2[], rri0i1[] and rri0i4[]  *
		 *-----------------------------------------------------------------*/

		l_fin_sup = LD8KConstants.MSIZE - 1;
		l_fin_inf = l_fin_sup - 1;
		ldec = LD8KConstants.NB_POS + 1;

		ptr_hd = 0;// h;
		ptr_hf = ptr_hd + 1;

		for (k = 0; k < LD8KConstants.NB_POS; k++) {

			p3 = rri2i3 + l_fin_sup;
			p2 = rri1i2 + l_fin_sup;
			p1 = rri0i1 + l_fin_sup;
			p0 = rri0i4 + l_fin_inf;
			cor = (float) 0.0;
			ptr_h1 = ptr_hd;
			ptr_h2 = ptr_hf;

			for (i = k + 1; i < LD8KConstants.NB_POS; i++) {

				cor += h[ptr_h1] * h[ptr_h2];
				ptr_h1++;
				ptr_h2++;
				cor += h[ptr_h1] * h[ptr_h2];
				ptr_h1++;
				ptr_h2++;
				rr[p3] = cor;

				cor += h[ptr_h1] * h[ptr_h2];
				ptr_h1++;
				ptr_h2++;
				rr[p2] = cor;

				cor += h[ptr_h1] * h[ptr_h2];
				ptr_h1++;
				ptr_h2++;
				rr[p1] = cor;

				cor += h[ptr_h1] * h[ptr_h2];
				ptr_h1++;
				ptr_h2++;
				rr[p0] = cor;

				p3 -= ldec;
				p2 -= ldec;
				p1 -= ldec;
				p0 -= ldec;
			}
			cor += h[ptr_h1] * h[ptr_h2];
			ptr_h1++;
			ptr_h2++;
			cor += h[ptr_h1] * h[ptr_h2];
			ptr_h1++;
			ptr_h2++;
			rr[p3] = cor;

			cor += h[ptr_h1] * h[ptr_h2];
			ptr_h1++;
			ptr_h2++;
			rr[p2] = cor;

			cor += h[ptr_h1] * h[ptr_h2];
			ptr_h1++;
			ptr_h2++;
			rr[p1] = cor;

			l_fin_sup -= LD8KConstants.NB_POS;
			l_fin_inf--;
			ptr_hf += LD8KConstants.STEP;
		}

		/*---------------------------------------------------------------------*
		 * Compute elements of: rri2i4[], rri1i3[], rri0i2[], rri1i4[], rri0i3 *
		 *---------------------------------------------------------------------*/

		ptr_hd = 0;// h;
		ptr_hf = ptr_hd + 2;
		l_fin_sup = LD8KConstants.MSIZE - 1;
		l_fin_inf = l_fin_sup - 1;
		for (k = 0; k < LD8KConstants.NB_POS; k++) {

			p4 = rri2i4 + l_fin_sup;
			p3 = rri1i3 + l_fin_sup;
			p2 = rri0i2 + l_fin_sup;
			p1 = rri1i4 + l_fin_inf;
			p0 = rri0i3 + l_fin_inf;

			cor = (float) 0.0;
			ptr_h1 = ptr_hd;
			ptr_h2 = ptr_hf;
			for (i = k + 1; i < LD8KConstants.NB_POS; i++) {

				cor += h[ptr_h1] * h[ptr_h2];
				ptr_h1++;
				ptr_h2++;
				rr[p4] = cor;

				cor += h[ptr_h1] * h[ptr_h2];
				ptr_h1++;
				ptr_h2++;
				rr[p3] = cor;

				cor += h[ptr_h1] * h[ptr_h2];
				ptr_h1++;
				ptr_h2++;
				rr[p2] = cor;

				cor += h[ptr_h1] * h[ptr_h2];
				ptr_h1++;
				ptr_h2++;
				rr[p1] = cor;

				cor += h[ptr_h1] * h[ptr_h2];
				ptr_h1++;
				ptr_h2++;
				rr[p0] = cor;

				p4 -= ldec;
				p3 -= ldec;
				p2 -= ldec;
				p1 -= ldec;
				p0 -= ldec;
			}
			cor += h[ptr_h1] * h[ptr_h2];
			ptr_h1++;
			ptr_h2++;
			rr[p4] = cor;

			cor += h[ptr_h1] * h[ptr_h2];
			ptr_h1++;
			ptr_h2++;
			rr[p3] = cor;

			cor += h[ptr_h1] * h[ptr_h2];
			ptr_h1++;
			ptr_h2++;
			rr[p2] = cor;

			l_fin_sup -= LD8KConstants.NB_POS;
			l_fin_inf--;
			ptr_hf += LD8KConstants.STEP;
		}

		/*----------------------------------------------------------------------*
		 * Compute elements of: rri1i4[], rri0i3[], rri2i4[], rri1i3[], rri0i2  *
		 *----------------------------------------------------------------------*/

		ptr_hd = 0;// h;
		ptr_hf = ptr_hd + 3;
		l_fin_sup = LD8KConstants.MSIZE - 1;
		l_fin_inf = l_fin_sup - 1;
		for (k = 0; k < LD8KConstants.NB_POS; k++) {

			p4 = rri1i4 + l_fin_sup;
			p3 = rri0i3 + l_fin_sup;
			p2 = rri2i4 + l_fin_inf;
			p1 = rri1i3 + l_fin_inf;
			p0 = rri0i2 + l_fin_inf;

			ptr_h1 = ptr_hd;
			ptr_h2 = ptr_hf;
			cor = (float) 0.0;
			for (i = k + 1; i < LD8KConstants.NB_POS; i++) {

				cor += h[ptr_h1] * h[ptr_h2];
				ptr_h1++;
				ptr_h2++;
				rr[p4] = cor;

				cor += h[ptr_h1] * h[ptr_h2];
				ptr_h1++;
				ptr_h2++;
				rr[p3] = cor;

				cor += h[ptr_h1] * h[ptr_h2];
				ptr_h1++;
				ptr_h2++;
				rr[p2] = cor;

				cor += h[ptr_h1] * h[ptr_h2];
				ptr_h1++;
				ptr_h2++;
				rr[p1] = cor;

				cor += h[ptr_h1] * h[ptr_h2];
				ptr_h1++;
				ptr_h2++;
				rr[p0] = cor;

				p4 -= ldec;
				p3 -= ldec;
				p2 -= ldec;
				p1 -= ldec;
				p0 -= ldec;
			}
			cor += h[ptr_h1] * h[ptr_h2];
			ptr_h1++;
			ptr_h2++;
			rr[p4] = cor;

			cor += h[ptr_h1] * h[ptr_h2];
			ptr_h1++;
			ptr_h2++;
			rr[p3] = cor;

			l_fin_sup -= LD8KConstants.NB_POS;
			l_fin_inf--;
			ptr_hf += LD8KConstants.STEP;
		}

		/*----------------------------------------------------------------------*
		 * Compute elements of: rri0i4[], rri2i3[], rri1i2[], rri0i1[]          *
		 *----------------------------------------------------------------------*/

		ptr_hd = 0;// h;
		ptr_hf = ptr_hd + 4;
		l_fin_sup = LD8KConstants.MSIZE - 1;
		l_fin_inf = l_fin_sup - 1;
		for (k = 0; k < LD8KConstants.NB_POS; k++) {

			p3 = rri0i4 + l_fin_sup;
			p2 = rri2i3 + l_fin_inf;
			p1 = rri1i2 + l_fin_inf;
			p0 = rri0i1 + l_fin_inf;

			ptr_h1 = ptr_hd;
			ptr_h2 = ptr_hf;
			cor = (float) 0.;
			for (i = k + 1; i < LD8KConstants.NB_POS; i++) {

				cor += h[ptr_h1] * h[ptr_h2];
				ptr_h1++;
				ptr_h2++;
				rr[p3] = cor;

				cor += h[ptr_h1] * h[ptr_h2];
				ptr_h1++;
				ptr_h2++;
				cor += h[ptr_h1] * h[ptr_h2];
				ptr_h1++;
				ptr_h2++;
				rr[p2] = cor;

				cor += h[ptr_h1] * h[ptr_h2];
				ptr_h1++;
				ptr_h2++;
				rr[p1] = cor;

				cor += h[ptr_h1] * h[ptr_h2];
				ptr_h1++;
				ptr_h2++;
				rr[p0] = cor;

				p3 -= ldec;
				p2 -= ldec;
				p1 -= ldec;
				p0 -= ldec;
			}
			cor += h[ptr_h1] * h[ptr_h2];
			ptr_h1++;
			ptr_h2++;
			rr[p3] = cor;

			l_fin_sup -= LD8KConstants.NB_POS;
			l_fin_inf--;
			ptr_hf += LD8KConstants.STEP;
		}
		return;
	}

	int extra;

	/*----------------------------------------------------------------------------
	 * d4i40_17 - algebraic codebook search 17 bits; 4 pulses 40 sampleframe
	 *----------------------------------------------------------------------------
	 */
	int d4i40_17( /* output: pulse positions */
	float dn[], /* input : backward filtered target vector */
			float rr[], /* input : autocorrelations of impulse response h[] */
			float h[], /* input : impulse response of filters */
			float cod[], /* output: selected algebraic codeword */
			float y[], /* output: filtered algebraic codeword */
			IntegerPointer signs, /* output: signs of 4 pulses */
			int i_subfr /* input : subframe flag */
	) {
		/*
		 * The code length is 40, containing 4 nonzero pulses i0, i1, i2, i3. with pulse spacings of step = 5 Each
		 * pulses can have 8 possible positions (positive or negative):
		 * 
		 * i0 (+-1) : 0, 5, 10, 15, 20, 25, 30, 35 i1 (+-1) : 1, 6, 11, 16, 21, 26, 31, 36 i2 (+-1) : 2, 7, 12, 17, 22,
		 * 27, 32, 37 i3 (+-1) : 3, 8, 13, 18, 23, 28, 33, 38 4, 9, 14, 19, 24, 29, 34, 39 --------------------
		 * -------------------------------------------------------
		 */
		int i0, i1, i2, i3, ip0, ip1, ip2, ip3;
		int i, j, time;
		float ps0, ps1, ps2, ps3, alp0, alp1, alp2, alp3;
		float ps3c, psc, alpha;
		float average, max0, max1, max2, thres;
		float p_sign[] = new float[LD8KConstants.L_SUBFR];

		int rri0i0, rri1i1, rri2i2, rri3i3, rri4i4;
		int rri0i1, rri0i2, rri0i3, rri0i4;
		int rri1i2, rri1i3, rri1i4;
		int rri2i3, rri2i4;

		int ptr_ri0i0, ptr_ri1i1, ptr_ri2i2, ptr_ri3i3, ptr_ri4i4;
		int ptr_ri0i1, ptr_ri0i2, ptr_ri0i3, ptr_ri0i4;
		int ptr_ri1i2, ptr_ri1i3, ptr_ri1i4;
		int ptr_ri2i3, ptr_ri2i4;

		/* Init pointers */

		rri0i0 = 0;// rr;
		rri1i1 = rri0i0 + LD8KConstants.NB_POS;
		rri2i2 = rri1i1 + LD8KConstants.NB_POS;
		rri3i3 = rri2i2 + LD8KConstants.NB_POS;
		rri4i4 = rri3i3 + LD8KConstants.NB_POS;

		rri0i1 = rri4i4 + LD8KConstants.NB_POS;
		rri0i2 = rri0i1 + LD8KConstants.MSIZE;
		rri0i3 = rri0i2 + LD8KConstants.MSIZE;
		rri0i4 = rri0i3 + LD8KConstants.MSIZE;
		rri1i2 = rri0i4 + LD8KConstants.MSIZE;
		rri1i3 = rri1i2 + LD8KConstants.MSIZE;
		rri1i4 = rri1i3 + LD8KConstants.MSIZE;
		rri2i3 = rri1i4 + LD8KConstants.MSIZE;
		rri2i4 = rri2i3 + LD8KConstants.MSIZE;

		/*-----------------------------------------------------------------------*
		 * Reset max_time for 1st subframe.                                      *
		 *-----------------------------------------------------------------------*
		 */
		if (i_subfr == 0)
			extra = 30;

		/*----------------------------------------------------------------------*
		 * Chose the signs of the impulses.                                      *
		 *-----------------------------------------------------------------------*/

		for (i = 0; i < LD8KConstants.L_SUBFR; i++) {
			if (dn[i] >= (float) 0.0) {
				p_sign[i] = (float) 1.0;
			} else {
				p_sign[i] = (float) -1.0;
				dn[i] = -dn[i];
			}
		}

		/*-------------------------------------------------------------------*
		 * - Compute the search threshold after three pulses                 *
		 *-------------------------------------------------------------------*/

		average = dn[0] + dn[1] + dn[2];
		max0 = dn[0];
		max1 = dn[1];
		max2 = dn[2];
		for (i = 5; i < LD8KConstants.L_SUBFR; i += LD8KConstants.STEP) {
			average += dn[i] + dn[i + 1] + dn[i + 2];
			if (dn[i] > max0)
				max0 = dn[i];
			if (dn[i + 1] > max1)
				max1 = dn[i + 1];
			if (dn[i + 2] > max2)
				max2 = dn[i + 2];
		}
		max0 += max1 + max2;
		average *= (float) 0.125; /* 1/8 */
		thres = average + (max0 - average) * LD8KConstants.THRESHFCB;

		/*-------------------------------------------------------------------*
		 * Modification of rrixiy to take into account signs.                *
		 *-------------------------------------------------------------------*/
		ptr_ri0i1 = rri0i1;
		ptr_ri0i2 = rri0i2;
		ptr_ri0i3 = rri0i3;
		ptr_ri0i4 = rri0i4;

		for (i0 = 0; i0 < LD8KConstants.L_SUBFR; i0 += LD8KConstants.STEP) {
			for (i1 = 1; i1 < LD8KConstants.L_SUBFR; i1 += LD8KConstants.STEP) {
				rr[ptr_ri0i1] *= (p_sign[i0] * p_sign[i1]);
				ptr_ri0i1++;
				rr[ptr_ri0i2] *= (p_sign[i0] * p_sign[i1 + 1]);
				ptr_ri0i2++;
				rr[ptr_ri0i3] *= (p_sign[i0] * p_sign[i1 + 2]);
				ptr_ri0i3++;
				rr[ptr_ri0i4] *= (p_sign[i0] * p_sign[i1 + 3]);
				ptr_ri0i4++;
			}
		}

		ptr_ri1i2 = rri1i2;
		ptr_ri1i3 = rri1i3;
		ptr_ri1i4 = rri1i4;

		for (i1 = 1; i1 < LD8KConstants.L_SUBFR; i1 += LD8KConstants.STEP) {
			for (i2 = 2; i2 < LD8KConstants.L_SUBFR; i2 += LD8KConstants.STEP) {
				rr[ptr_ri1i2] *= (p_sign[i1] * p_sign[i2]);
				ptr_ri1i2++;
				rr[ptr_ri1i3] *= (p_sign[i1] * p_sign[i2 + 1]);
				ptr_ri1i3++;
				rr[ptr_ri1i4] *= (p_sign[i1] * p_sign[i2 + 2]);
				ptr_ri1i4++;
			}
		}

		ptr_ri2i3 = rri2i3;
		ptr_ri2i4 = rri2i4;

		for (i2 = 2; i2 < LD8KConstants.L_SUBFR; i2 += LD8KConstants.STEP) {
			for (i3 = 3; i3 < LD8KConstants.L_SUBFR; i3 += LD8KConstants.STEP) {
				rr[ptr_ri2i3] *= (p_sign[i2] * p_sign[i3]);
				ptr_ri2i3++;
				rr[ptr_ri2i4] *= (p_sign[i2] * p_sign[i3 + 1]);
				ptr_ri2i4++;
			}
		}

		/*-------------------------------------------------------------------*
		 * Search the optimum positions of the four  pulses which maximize   *
		 *     square(correlation) / energy                                  *
		 * The search is performed in four  nested loops. At each loop, one  *
		 * pulse contribution is added to the correlation and energy.        *
		 *                                                                   *
		 * The fourth loop is entered only if the correlation due to the     *
		 *  contribution of the first three pulses exceeds the preset        *
		 *  threshold.                                                       *
		 *-------------------------------------------------------------------*/

		/* Default values */

		ip0 = 0;
		ip1 = 1;
		ip2 = 2;
		ip3 = 3;
		psc = (float) 0.0;
		alpha = (float) 1000000.0;
		time = LD8KConstants.MAX_TIME + extra;

		/* Four loops to search innovation code. */
		ptr_ri0i0 = rri0i0; /* Init. pointers that depend on first loop */
		ptr_ri0i1 = rri0i1;
		ptr_ri0i2 = rri0i2;
		ptr_ri0i3 = rri0i3;
		ptr_ri0i4 = rri0i4;

		end_search: for (i0 = 0; i0 < LD8KConstants.L_SUBFR; i0 += LD8KConstants.STEP) /*
																						 * first pulse loop
																						 */
		{
			ps0 = dn[i0];
			alp0 = rr[ptr_ri0i0++];

			ptr_ri1i1 = rri1i1; /* Init. pointers that depend on second loop */
			ptr_ri1i2 = rri1i2;
			ptr_ri1i3 = rri1i3;
			ptr_ri1i4 = rri1i4;

			for (i1 = 1; i1 < LD8KConstants.L_SUBFR; i1 += LD8KConstants.STEP) /*
																				 * second pulse loop
																				 */
			{
				ps1 = ps0 + dn[i1];
				alp1 = alp0 + rr[ptr_ri1i1++] + (float) 2.0 * rr[ptr_ri0i1++];

				ptr_ri2i2 = rri2i2; /* Init. pointers that depend on third loop */
				ptr_ri2i3 = rri2i3;
				ptr_ri2i4 = rri2i4;

				for (i2 = 2; i2 < LD8KConstants.L_SUBFR; i2 += LD8KConstants.STEP) {
					ps2 = ps1 + dn[i2];
					alp2 = alp1 + rr[ptr_ri2i2++] + (float) 2.0 * (rr[ptr_ri0i2++] + rr[ptr_ri1i2++]);

					if (ps2 > thres) {
						ptr_ri3i3 = rri3i3; /*
											 * Init. pointers that depend on 4th loop
											 */

						for (i3 = 3; i3 < LD8KConstants.L_SUBFR; i3 += LD8KConstants.STEP) {
							ps3 = ps2 + dn[i3];
							alp3 = alp2 + rr[ptr_ri3i3++] + (float) 2.0
									* (rr[ptr_ri1i3++] + rr[ptr_ri0i3++] + rr[ptr_ri2i3++]);

							ps3c = ps3 * ps3;
							if ((ps3c * alpha) > (psc * alp3)) {
								psc = ps3c;
								alpha = alp3;
								ip0 = i0;
								ip1 = i1;
								ip2 = i2;
								ip3 = i3;
							}
						} /* end of for i3 = */

						ptr_ri0i3 -= LD8KConstants.NB_POS;
						ptr_ri1i3 -= LD8KConstants.NB_POS;

						ptr_ri4i4 = rri4i4; /*
											 * Init. pointers that depend on 4th loop
											 */

						for (i3 = 4; i3 < LD8KConstants.L_SUBFR; i3 += LD8KConstants.STEP) {
							ps3 = ps2 + dn[i3];
							alp3 = alp2 + rr[ptr_ri4i4++] + (float) 2.0
									* (rr[ptr_ri1i4++] + rr[ptr_ri0i4++] + rr[ptr_ri2i4++]);

							ps3c = ps3 * ps3;
							if ((ps3c * alpha) > (psc * alp3)) {
								psc = ps3c;
								alpha = alp3;
								ip0 = i0;
								ip1 = i1;
								ip2 = i2;
								ip3 = i3;
							}
						} /* end of for i3 = */
						ptr_ri0i4 -= LD8KConstants.NB_POS;
						ptr_ri1i4 -= LD8KConstants.NB_POS;

						time--;
						if (time <= 0)
							break end_search; /* Maximum time finish */

					} /* end of if >thres */
					else {
						ptr_ri2i3 += LD8KConstants.NB_POS;
						ptr_ri2i4 += LD8KConstants.NB_POS;
					}

				} /* end of for i2 = */

				ptr_ri0i2 -= LD8KConstants.NB_POS;
				ptr_ri1i3 += LD8KConstants.NB_POS;
				ptr_ri1i4 += LD8KConstants.NB_POS;

			} /* end of for i1 = */

			ptr_ri0i2 += LD8KConstants.NB_POS;
			ptr_ri0i3 += LD8KConstants.NB_POS;
			ptr_ri0i4 += LD8KConstants.NB_POS;

		} /* end of for i0 = */

		extra = time;

		/* Find the codeword corresponding to the selected positions */

		for (i = 0; i < LD8KConstants.L_SUBFR; i++)
			cod[i] = (float) 0.0;
		cod[ip0] = p_sign[ip0];
		cod[ip1] = p_sign[ip1];
		cod[ip2] = p_sign[ip2];
		cod[ip3] = p_sign[ip3];

		/* find the filtered codeword */

		for (i = 0; i < LD8KConstants.L_SUBFR; i++)
			y[i] = (float) 0.0;

		if (p_sign[ip0] > (float) 0.0)
			for (i = ip0, j = 0; i < LD8KConstants.L_SUBFR; i++, j++)
				y[i] = h[j];
		else
			for (i = ip0, j = 0; i < LD8KConstants.L_SUBFR; i++, j++)
				y[i] = -h[j];

		if (p_sign[ip1] > (float) 0.0)
			for (i = ip1, j = 0; i < LD8KConstants.L_SUBFR; i++, j++)
				y[i] = y[i] + h[j];
		else
			for (i = ip1, j = 0; i < LD8KConstants.L_SUBFR; i++, j++)
				y[i] = y[i] - h[j];

		if (p_sign[ip2] > (float) 0.0)
			for (i = ip2, j = 0; i < LD8KConstants.L_SUBFR; i++, j++)
				y[i] = y[i] + h[j];
		else
			for (i = ip2, j = 0; i < LD8KConstants.L_SUBFR; i++, j++)
				y[i] = y[i] - h[j];

		if (p_sign[ip3] > (float) 0.0)
			for (i = ip3, j = 0; i < LD8KConstants.L_SUBFR; i++, j++)
				y[i] = y[i] + h[j];
		else
			for (i = ip3, j = 0; i < LD8KConstants.L_SUBFR; i++, j++)
				y[i] = y[i] - h[j];

		/* find codebook index; 4 bit signs + 13 bit positions */

		i = 0;
		if (p_sign[ip0] > (float) 0.0)
			i += 1;
		if (p_sign[ip1] > (float) 0.0)
			i += 2;
		if (p_sign[ip2] > (float) 0.0)
			i += 4;
		if (p_sign[ip3] > (float) 0.0)
			i += 8;
		signs.value = i;

		ip0 = ip0 / 5;
		ip1 = ip1 / 5;
		ip2 = ip2 / 5;
		j = (ip3 % 5) - 3;
		ip3 = ((ip3 / 5) << 1) + j;

		i = (ip0) + (ip1 << 3) + (ip2 << 6) + (ip3 << 9);

		return i;
	}

}
